package com.yanfan.framework.utils;

import com.yanfan.common.annotation.CacheBatchEvict;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Set;
import java.util.regex.Pattern;

@Slf4j
public class CacheBatchAnnotationUtils {


    public static String generateKeyListBySpEL(Method method, Object[] args, String spEL) {

        // 创建解析器
        SpelExpressionParser parser = new SpelExpressionParser();
        // 获取表达式
        Expression expression = parser.parseExpression(spEL);
        // 设置解析上下文
        EvaluationContext context = new StandardEvaluationContext();
        // 获取运行时参数名称
        DefaultParameterNameDiscoverer discover = new DefaultParameterNameDiscoverer();
        String[] parameterNames = discover.getParameterNames(method);
        assert parameterNames != null;
        for (int i = 0; i < parameterNames.length; i++) {
            context.setVariable(parameterNames[i], args[i]);
        }
        // 解析
        String value = expression.getValue(context, String.class);
        if (StringUtils.isEmpty(value)) {
            return null;
        }
        return value;
    }

    public static void cacheBatchEvict(Method method, Object[] args, CacheBatchEvict cacheBatchEvict) {
        String cacheName = cacheBatchEvict.cacheNames();
        // 清空所有缓存
        if (cacheBatchEvict.isClearAll()) {
            CacheUtils.clear(cacheName);
            return;
        }

        String spEL = cacheBatchEvict.key();
        if (!StringUtils.hasText(spEL)) {
            log.warn("@CacheBatchEvict key is null");
            return;
        }
        // 2.获取目标方法参数
        String key = generateKeyListBySpEL(method, args, spEL);
        if (key == null) {
            log.warn(String.format("unable to find method params by [%s]", spEL));
            return;
        }

        // 3.清除缓存
        // 获取 缓存中的key 进行正则匹配匹配成功则删除
        Set<Object> cacheKeys = CacheUtils.keys(cacheName);
        Pattern pattern = Pattern.compile(key);
        for (Object cacheKey : cacheKeys) {
            String cacheKeyStr = String.valueOf(cacheKey);
            if (pattern.matcher(cacheKeyStr).find()) {
                CacheUtils.evict(cacheName, key);
            }
        }
    }
}
